/**
 * This class encapsulates a static table model that is guaranteed to have the latest values as displayed on the main
 * table
 */
package slhs.tempo.TableAnalyzer;

import java.util.HashMap;

import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

/**
 * TableModelUpdater.java
 * 
 * @author Swapnil Devikar
 * 
 */
public class ConcreteTableModelListener implements TableModelListener {

    private static DefaultTableModel updatedModel;
    public static HashMap<String, Integer> columnHeaderMap = new HashMap<String, Integer>();
    private int columnCount = 0;
    private JTable table;
    private DefaultTableModel model;

    public ConcreteTableModelListener(JTable table) {
	this.table = table;
	model = (DefaultTableModel) table.getModel();
	this.setTableModel(model);
	this.columnCount = model.getColumnCount();
	for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
	    columnHeaderMap.put(model.getColumnName(columnIndex), columnIndex);
	}
    }

    /**
     * Helper method that updates the updatedModel and column headers on each table model event
     * */
    private void update(TableModel dataModel) {
	int modelRowCount = table.getRowCount();
	int modelColumnCount = table.getColumnCount();
	DefaultTableModel newModel = new DefaultTableModel();
	newModel.setColumnCount(modelColumnCount);
	newModel.setRowCount(modelRowCount);
	for (int rowIndex = 0; rowIndex < modelRowCount; rowIndex++) {
	    for (int columnIndex = 0; columnIndex < modelColumnCount; columnIndex++) {
		int viewIndex = table.convertRowIndexToModel(rowIndex);
		Object value = dataModel.getValueAt(viewIndex, columnIndex);
		newModel.setValueAt(value, rowIndex, columnIndex);
	    }
	}
	// update column headers
	columnCount = newModel.getColumnCount();
	columnHeaderMap = new HashMap<String, Integer>();
	for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
	    columnHeaderMap.put(model.getColumnName(columnIndex), columnIndex);
	}
	// update model
	updatedModel = newModel;
    }

    /**
     * Returns the latest table data model
     * 
     * @return updatedDataModel
     * */
    public static TableModel getUpdatedModel() {
	return updatedModel;
    }

    /**
     * Returns index of the column in the latest datamodel
     * 
     * @param columnHeader
     *            - column name whose index is required to be found out
     * @return Index of the column header in the datamodel or -1 if the header doesn't exist
     * */
    public static int getColumnIndexByName(String columnHeader) {

	return columnHeaderMap.get(columnHeader);
    }

    /**
     * This method is intended to be used only once to initialize table data model, in case user decides to do NO
     * CHANGES to the imported table at all
     * */
    private void setTableModel(DefaultTableModel dataModel) {
	updatedModel = dataModel;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.swing.event.TableModelListener#tableChanged(javax.swing.event.TableModelEvent)
     */
    @Override
    public void tableChanged(TableModelEvent event) {
	// could be more selective for table updates, but for now, updating the table model for each table model event
	DefaultTableModel dataModel = (DefaultTableModel) event.getSource();
	// construct a new table from datamodel
	update(dataModel);
    }

}
